import asyncio
import websockets
import os
from pathlib import Path
from flask import Flask, request, jsonify
import threading
import subprocess
import logging
import uuid
import time
import platform
import signal
import re
from  picforgifupload import EventUploader
from  usb_mount import handle_usb_storage
# 假设这些模块已经正确定义
from videofilesystem import build_video_queue, get_parent_dir, modify_queue_info, extract_videos_direct, mark_video_processed, read_video_queue_from_json, mount_usb
from videofilesystem import extract_parent_directory, get_latest_image, adjust_priority_and_pause, reset_video_processed_status, create_nested_folders
import json
from queue import Queue
from cpp_status import is_npu_idle
import getcamerainfo

import sendcameradealinfo
from sendfile import VideoAPIUploader
import videofilesystem
# from gengif import EventUploader
from gen_config import create_video_config, gen_sdkconfig
import subprocess
from set_camera_status import change_video_state
from werkzeug.utils import secure_filename
from asynccpp import call_run_cpp_api_async , stop_cpp_process, _mv, _scp
from  trimvideo import  split_video , split_back
from  picforgifuploadasync import AsyncUploadService
from sendquickimagea import MetadataSender
from  calframe import get_video_frame_count
from upload_image_to_server import  clear_jpg_images
index_event = {
    "1":"problem_car",
    "2":"problem_cross",
    "3":"problem_occupy_road",
    "4":"problem_parking",
    "5":"problem_pet",
    "6":"garbage_0",
    "7":"garbage_1",
    "8":"garbage_2",
    "9":"garbage_3"
}

def safe_filename(filename):
    """
    改进的安全文件名处理函数
    保留原始文件扩展名，正确处理点(.)
    """
    # 分离文件名和扩展名
    name, ext = os.path.splitext(filename)
    
    # 处理主文件名部分
    name = re.sub(r'[^\w\-]', '_', name)  # 替换非安全字符为下划线
    name = name.strip('_')  # 去除首尾下划线
    
    # 处理扩展名部分
    ext = ext.lower()  # 统一扩展名为小写
    ext = re.sub(r'[^a-z0-9.]', '', ext)  # 只保留字母数字和点
    print()
    # 组合最终文件名
    if ext and not ext.startswith('.'):
        ext = '.' + ext
    return f"{name[:200]}{ext}"  #限制总长度

class VideoProcessingApp:
    def __init__(self,
                 root_dir="/mnt/usb/video",
                 output_dir="generated_images",
                 host='0.0.0.0',
                 port=5000,
                 lastest_img="test.jpg",
                 send_interval=0.3
                 ):
        self.app = Flask(__name__)
        self.root_dir = root_dir
        self.output_dir = output_dir
        self.host = host
        self.port = port
        self.demonstrate = False
        self.cpp_pid = -1
        self.run_moive_task = ""
        self.is_paused = False
        self.video_queue = ""
        self.processing_thread = None
        os.makedirs(self.output_dir, exist_ok=True)
        self._register_routes()
        self.lastest_img = lastest_img
        self.completed_count=0
        self.SEND_INTERVAL = send_interval
        # self.WS_PORT = ws_port
        # self.ws_stop_flag = asyncio.Event()  # 异步停止标志
        # self.ws_server = None
        # self.ws_server_task = None
        self.stop_condition = None  # 停止条件值
        self.completed_gif_count = 0
    

    def _register_routes(self):
        @self.app.route('/start', methods=['POST'])
        def _start():
            return self.run_program()

        @self.app.route('/read', methods=['POST'])
        def _getdiskinfo():
            return self.self_mount_usb()
        
        @self.app.route('/increment_count', methods=['POST'])
        def _increment_count():
            return self.increment_completed_count()
        
        @self.app.route('/increment_gif_count', methods=['POST'])
        def _increment_gif_count():
            return self.increment_gif_completed_count()

        @self.app.route('/save_images', methods=['POST'])
        def save_images():
            try:
                # 获取参数
                camera = request.form.get('cameraName')
                video = request.form.get('videoName')
                event = request.form.get('event')
                image_files = request.files.getlist('images')
                
                # 参数验证
                if not all([camera, video]) or not image_files:
                    return jsonify({
                        "status": "error",
                        "message": "缺少必要参数(cameraName/videoName/images)"
                    }), 400

                # 创建目录
                save_dir = os.path.join(os.path.abspath("./"), camera, video, index_event[event])
                os.makedirs(save_dir, exist_ok=True)
                
                saved_paths = []
                
                # 处理每个文件
                for img in image_files:
                    if not img.filename:
                        continue

                    # 生成安全文件名
                    original_name = img.filename
                    # print("original_name:",original_name)
                    safe_name = safe_filename(original_name)
                    # print("safe_name:",safe_name)
                    # 处理重名文件
                    save_path = os.path.join(save_dir, safe_name)
                    counter = 1
                    while os.path.exists(save_path):
                        name, ext = os.path.splitext(safe_name)
                        save_path = os.path.join(save_dir, f"{name}_{counter}{ext}")
                        counter += 1

                    # 确保二进制写入
                    img.seek(0)  # 重置文件指针
                    with open(save_path, 'wb') as f:
                        f.write(img.read())
                    
                    saved_paths.append(save_path)

                return jsonify({
                    "status": "success",
                    "saved_count": len(saved_paths),
                    "saved_paths": saved_paths,
                    "camera": camera,
                    "video": video,
                    "timestamp": time.time()
                })

            except Exception as e:
                return jsonify({
                    "status": "error",
                    "message": f"保存失败: {str(e)}",
                    "timestamp": time.time()
                }), 500


        @self.app.route('/stopone', methods=['POST'])
        def _stop():
            action = request.json.get('action') if request.is_json else None
            return self.stop_cpp(action=action)

        @self.app.route('/stopbatch', methods=['POST'])
        def _stop_batch():
            return self.stop_cpp_batch()

        @self.app.route('/startone', methods=['POST'])
        def _startone():
            action = request.json.get('action') if request.is_json else None
            return self.start_cpp(action=action)

        @self.app.route('/demonstrateone', methods=['POST'])
        def _demonstrateone():
            print("demonstrateone fun")
            # print(request)
            camera = request.json.get('cameraName') if request.is_json else None
            video = request.json.get('videoName') if request.is_json else None

            # print(camera,video)
            if not camera:
                return jsonify({"status": "error", "message": "请求数据为空，请提供 JSON 格式的请求数据"}), 400
            return self.demonstrate_cpp(camera=camera,video=video,sendinfo=True,restart=True)

        @self.app.route('/startsinglevideo', methods=['POST'])
        def _startsinglevideo():
            # print("demonstrateone fun")
            # print(request)
            camera = request.json.get('cameraName') if request.is_json else None
            video = request.json.get('videoName') if request.is_json else None

            # print(camera,video)
            if not camera:
                return jsonify({"status": "error", "message": "请求数据为空，请提供 JSON 格式的请求数据"}), 400
            return self.demonstrate_cpp(camera=camera,video=video, sendinfo=False)
        
        @self.app.route('/restartsinglevideo', methods=['POST'])
        def _restartsinglevideo():
            # print("demonstrateone fun")
            # print(request)
            camera = request.json.get('cameraName') if request.is_json else None
            video = request.json.get('videoName') if request.is_json else None

            # print(camera,video)
            if not camera:
                return jsonify({"status": "error", "message": "请求数据为空，请提供 JSON 格式的请求数据"}), 400
            return self.demonstrate_cpp(camera=camera,video=video, sendinfo=False,restart=True)

        @self.app.route('/startbatch', methods=['POST'])
        def _start_batch():
            action = request.json.get('action') if request.is_json else None
            return self.start_cpp_batch(action=action)

    def increment_completed_count(self):
        """增加完成计数"""
        try:
            print("访问here")
            self.completed_count += 1

            return jsonify({
                "status": "success",
                "completed_count": self.completed_count,
                "timestamp": time.time()
            })
        except Exception as e:
            return self._error_response(f"计数增加失败: {str(e)}")

    def increment_gif_completed_count(self):
        """增加完成计数"""
        try:
            print("访问here")
            self.completed_gif_count += 1

            return jsonify({
                "status": "success",
                "completed_count": self.completed_gif_count,
                "timestamp": time.time()
            })
        except Exception as e:
            return self._error_response(f"计数增加失败: {str(e)}")

    def self_mount_usb(self):
        if(not handle_usb_storage()):
            result = "load u disk failed"
            return jsonify({
            "status": "failed",
            "results": result
            })
        self.video_queue = build_video_queue(self.root_dir, reread=True)
        print("dsdsd")
        config = {
            "root_dir": self.root_dir,
            "api_endpoint": "http://192.168.0.142:80/aiApi/aiSaveVideo",
            "timeout": 45,
            "max_retries": 3
        }

        uploader = VideoAPIUploader(**config)
        result = uploader.execute_upload()

        # 启动后台处理线程
        process_thread = threading.Thread(
            target=split_back,
            args=(self.video_queue,)  # 传递视频队列
        )
        process_thread.daemon = True  # 设置为守护线程
        process_thread.start()
        time.sleep(30)
        # 处理上传结果
        response_data = {
            "status": "success" if result.get('status') == 'success' else "failed",
            "results": result
        }
        
        if response_data["status"] == "success":
            print(f"上传成功！响应数据：{result.get('data')}")
        else:
            print(f"错误发生：{result.get('error_type')}")
            print(f"错误信息：{result.get('message')}")
            if 'status_code' in result:
                print(f"HTTP状态码：{result.get('status_code')}")

        return jsonify(response_data)


    def _error_response(self, message, status_code=500):
        return jsonify({
            "status": "error",
            "message": message
        }), status_code

    def run_program(self, send_info=True):
        try:   
            needprocess = extract_videos_direct(self.video_queue)
            self.is_paused = False
            print("needprocess: ", needprocess)
            for task in needprocess:
                self.completed_count=0
                self.completed_gif_count =0
                device_num =4
                start_time = time.time()
                # print("task:",task)
                result = change_video_state(
                    camera_name=task["camera"],
                    video_name=task["video"].split('.')[0],
                    state=0
                )
                for i in index_event:
                    create_nested_folders(task["camera"], task["video"].split('.')[0] ,event= index_event[i])
                print("创建文件夹OK")
                print(task["video_path"], task["video"].split('.')[0] )
                try:
                    split_video(task["video_path"], task["video"].split('.')[0], device_num)
                except Exception as e:
                    print(f"后台任务执行失败: {str(e)}")
                
                threading.Thread(target=_mv, args=("./" + task["video"].split('.')[0]+"_1.mp4","/data/processvideo/" + task["video"].split('.')[0]+".mp4" ),  daemon=True).start()
                threading.Thread(target=_scp, args=("./" + task["video"].split('.')[0]+"_2.mp4", "linaro@192.168.0.188", "/data/processvideo/" + task["video"].split('.')[0]+".mp4"),  daemon=True).start()
                
                video_frame = get_video_frame_count("./" + task["video"].split('.')[0]+"_1.mp4" )
                print(video_frame, "video_frame")
                asyncio.run(call_run_cpp_api_async(
                    host='192.168.0.186',
                    send_info=False,
                    camera_name = task["camera"],
                    video_name = task["video"].split('.')[0]
                    

                ))
                asyncio.run(call_run_cpp_api_async(
                    host='192.168.0.188',
                    send_info=False,
                    camera_name = task["camera"],
                    video_name = task["video"].split('.')[0],
                    image_base_index = video_frame

                ))
                try:
                        clear_jpg_images("/data/control_communication/" + task["camera"] +"/"+ task["video"].split('.')[0] + "/problem_cross")
                except Exception as e:
                    print(f"后台任务执行失败: {str(e)}")

                # self.run_moive_task = get_parent_dir(task["video_path"])
                # print(task["video_path"], "---------", get_parent_dir(task["video_path"]))
                # if send_info:
                #     gen_sdkconfig(task["video_path"], get_parent_dir(task["video_path"]),save_pic_=1)
                # else:
                #     gen_sdkconfig(task["video_path"], get_parent_dir(task["video_path"]))
                # print("camera: ", task["camera"])
                # print("video:", task["video"].replace('.', '_'))
                # self.run_cpp_program(send_info=send_info)
                while( not self.is_paused and self.completed_count<2  ):
                    time.sleep(1)
                    # print(self.completed_count)

                #此处理论上收到了 四台机器的所有信息收集到所有gif图像后上传 
                if self.is_paused:
                    self.completed_count = 0
                    break

                print("self.is_paused:----------- ", self.is_paused)
                while( not self.is_paused and self.completed_gif_count<2  ):
                        time.sleep(1)
                        print(f"处理该视频经过的时间: {elapsed_time} 秒")
                        sender = MetadataSender()

                if not self.is_paused:
                    print("上传gif到远端机")
                    upload_service = AsyncUploadService()

                    # 非阻塞提交上传任务
                    future = upload_service.upload_images(
                        source_dir=("/data/control_communication/"  + task["camera"] + "/" + task["video"].split('.')[0] +"/"+index_event["2"]  ),
                        api_url="http://192.168.0.142:80/aiApi/saveEvent",
                        camera_name= task["camera"],
                        video_name= task["video"].split('.')[0],
                        algorithm_id="1"
                    )
                    end_time = time.time()
                    elapsed_time = end_time - start_time
                    print(f"处理该视频经过的时间: {elapsed_time} 秒")

                    while( not self.is_paused and self.completed_count<2  ):
                        time.sleep(1)
                    
                    sender = MetadataSender()
                    response = sender.send_metadata(
                        api_url="http://192.168.0.142:80/aiApi/saveQuickInfo",
                        camera_name=task["camera"],
                        video_name=task["video"].split('.')[0]
                    )

                    print("上传gif到远端机OK")
                    change_video_state(
                        camera_name=task["camera"],
                        video_name=task["video"].split('.')[0],
                        state=1
                    )   

                    print(f"成功上传: {report['success']}/{report['total']}")                  
                    mark_video_processed(self.video_queue, extract_parent_directory(task["video_path"]), task["video_path"])
                    self.save_process()
                output_file = "/data/newvideo_queue_info.json"
                try:
                    with open(output_file, 'w', encoding='utf-8') as f:
                        json.dump(self.video_queue, f, ensure_ascii=False, indent=4)
                except Exception as e:
                    print(f"写入 JSON 文件时出错: {e}")
                
            self.cpp_pid = -1
        except json.JSONDecodeError as e:
            print("error")
            return self._error_response(f"队列文件格式错误: {str(e)}")
        except IOError as e:
            print("error1")
            return self._error_response(f"文件操作失败: {str(e)}")
        except Exception as e:
            print("error2")
            return self._error_response(str(e))

    def save_process(self):
        output_file = os.path.join(self.root_dir, "video_queue_info.json")
        try:
            with open(output_file, 'w', encoding='utf-8') as f:
                json.dump(self.video_queue, f, ensure_ascii=False, indent=4)
        except Exception as e:
            print(f"写入 JSON 文件时出错: {e}")

    def run_cpp_program(self, send_info=True):
        try:
            output_path = os.path.join(
                self.output_dir,
                f"output_{uuid.uuid4().hex}.ppm"
            )
            cmd_ = "/home/linaro/.vs/sdk-test/build/bin/sdk-test"
            process = subprocess.Popen(
                [cmd_],
                stdout=subprocess.PIPE,
                stderr=subprocess.PIPE,
                text=True,
                encoding='utf-8',
                errors='replace'
            )
            output, error = "", ""
            self.cpp_pid = process.pid
            print("send_info: ", send_info)
            # send_info =True
            # if send_info:
            #     # 启动WebSocket服务器
            #     self.start_ws_server()
            while True:
                print("----cpp")
                time.sleep(1)
                out_line = process.stdout.readline()
                if out_line:
                    output += out_line
                    print(f"[STDOUT] {out_line.strip()}")
                err_line = process.stderr.readline()
                if err_line:
                    error += err_line
                    print(f"[STDERR] {err_line.strip()}")
                if process.poll() is not None:
                    print("stop")
                    break
            print("当前cpp函数结束")
            # if send_info:
            #     self.stop_ws_server()
        except Exception as e:
            return self._error_response(f"{str(e)}\n[Error Output] {error}")

    def _async_execute(self, send_info=False):
        if self.processing_thread and self.processing_thread.is_alive():
            if self.cpp_pid != -1:
                try:
                    # os.kill(self.cpp_pid, signal.SIGKILL)
                    self.cpp_pid = -1
                    stop_cpp_process(ip="192.168.0.186")
                    stop_cpp_process(ip="192.168.0.188")
                except ProcessLookupError:
                    pass
            self.is_paused = True
        time.sleep(1)
        self.processing_thread = threading.Thread(
            target=self._run_program_wrapper,
            kwargs={'send_info': send_info}
        )
        self.processing_thread.start()

    def _run_program_wrapper(self, send_info=False):
        try:
            self.run_program(send_info=send_info)
        except Exception as e:
            logging.error(f"异步执行异常: {str(e)}")

    def stop_cpp(self, action=None):
        self.completed_count=0
        self.completed_gif_count =0
        print("only stop flag")
        print("here", (self.root_dir + "/" + action))
        print(self.video_queue)
        output_file = "/data/video_queue_info2.json"
        self.is_paused = True
        print("self.is_paused in stop_cpp : ", self.is_paused)
        if action == self.run_moive_task:
            print("action == self.run_moive_task")
            print("self.cpp_pid: ", self.cpp_pid)
            # if self.cpp_pid != -1:
            #     print("kill self.cpp_pid: ", self.cpp_pid)
            stop_cpp_process(ip="192.168.0.186")
            stop_cpp_process(ip="192.168.0.188")
            modify_queue_info(self.video_queue, self.root_dir + "/" + action, queue_paused=True, custom_field=123)
            try:
                with open(output_file, 'w', encoding='utf-8') as f:
                    json.dump(self.video_queue, f, ensure_ascii=False, indent=4)
            except Exception as e:
                print(f"写入 JSON 文件时出错: {e}")
            self._async_execute()
        else:
            stop_cpp_process(ip="192.168.0.186")
            stop_cpp_process(ip="192.168.0.188")
            print("------------------1")
            modify_queue_info(self.video_queue, self.root_dir + "/" + action, queue_paused=True, custom_field=123)
            print("------------------2")
            try:
                with open(output_file, 'w', encoding='utf-8') as f:
                    json.dump(self.video_queue, f, ensure_ascii=False, indent=4)
            except Exception as e:
                print(f"写入 JSON 文件时出错: {e}")
            self._async_execute()
        results = []
        return jsonify({
            "status": "completed",
            "results": results
        })

    def stop_cpp_batch(self):
        output_file = "/data/video_queue_info3.json"
        try:
            data = request.get_json()
            self.is_paused = True
            if not data or 'camera_paths' not in data:
                return self._error_response("缺少camera_paths参数", 400)
            camera_paths = data['camera_paths']
            if not isinstance(camera_paths, list):
                return self._error_response("camera_paths必须是数组", 400)
            results = []
            for path in camera_paths:
                try:
                    if path == self.run_moive_task:
                        # if self.cpp_pid != -1:
                        #     os.kill(self.cpp_pid, signal.SIGKILL)
                        stop_cpp_process(ip="192.168.0.186")
                        stop_cpp_process(ip="192.168.0.188")
                        self.cpp_pid = -1
                    modify_queue_info(self.video_queue, self.root_dir + "/" + path, queue_paused=True, custom_field=123)
                    results.append({
                        "camera_path": path,
                        "status": "success",
                        "stopped": (path == self.run_moive_task)
                    })
                except Exception as e:
                    results.append({
                        "camera_path": path,
                        "status": "error",
                        "message": str(e)
                    })
            with open(output_file, 'w', encoding='utf-8') as f:
                json.dump(self.video_queue, f, ensure_ascii=False, indent=4)
            self.is_paused = True
            self._async_execute()
            return jsonify({
                "status": "completed",
                "results": results
            })
        except Exception as e:
            return self._error_response(str(e))

    def demonstrate_start(self, action=None):
        output_file = "/data/video_queue_info4.json"
        print("hhhh")
        try:
            if not action:
                return self._error_response("缺少摄像头路径参数", 400)
            demonstrate = True
            # if self.cpp_pid != -1:
            #     os.kill(self.cpp_pid, signal.SIGKILL)
            stop_cpp_process(ip="192.168.0.186")
            stop_cpp_process(ip="192.168.0.188")
            self.is_paused = True
            camera, video = action.split('/')
            video_path = find_videopath_by_camera_movie(camera, video, self.video_queue)
            gen_sdkconfig(task["video_path"], get_parent_dir(task["video_path"]),save_pic_=1)
            time.sleep(1)
            self.run_cpp_program(send_info = True)
            self._async_execute()
            return jsonify({
                "status": "success",
                "message": f"摄像头任务已启动: {action}",
                "resumed": (action == self.run_moive_task)
            })
        except Exception as e:
            return self._error_response(str(e))

    def start_cpp(self, action=None):
        output_file = "/data/video_queue_info4.json"
        print("hhhh")
        try:
            if not action:
                return self._error_response("缺少摄像头路径参数", 400)
            self.is_paused = True
            print("self.is_paused in start_cpp : ", self.is_paused)
            modify_queue_info(self.video_queue, self.root_dir + "/" + action, queue_paused=False, custom_field=123)
            # print("begin")
            with open(output_file, 'w', encoding='utf-8') as f:
                json.dump(self.video_queue, f, ensure_ascii=False, indent=4)
            self._async_execute()
            return jsonify({
                "status": "success",
                "message": f"摄像头任务已启动: {action}",
                "resumed": (action == self.run_moive_task)
            })
        except Exception as e:
            return self._error_response(str(e))

    def demonstrate_cpp(self, camera=None, video=None,sendinfo=True, restart=False):
        output_file = "/data/video_queue_info5.json"
        print("hhhh")
        camera_name = camera
        video_name = video
        try:
            if not camera_name:
                return self._error_response("缺少摄像头视频参数", 400)
            self.is_paused = True
            print("demonstrate_cpp output_file: ", output_file)
            print("self.root_dir camera_name: ", self.root_dir + "/" + camera_name)
            if restart and sendinfo:
                print("ss-------s")
                reset_video_processed_status(self.video_queue,  self.root_dir + "/" + camera_name, video_name+".mp4" )
                print("sss")
                adjust_priority_and_pause(self.video_queue,  self.root_dir + "/" + camera_name, video_name+".mp4" )
            if restart and (not sendinfo):
                print("xxx-------s")
                reset_video_processed_status(self.video_queue,  self.root_dir + "/" + camera_name, video_name+".mp4" )
                adjust_priority_and_pause(self.video_queue,  self.root_dir + "/" + camera_name, video_name+".mp4" )
            if (not restart) and (not sendinfo):
                adjust_priority_and_pause(self.video_queue,  self.root_dir + "/" + camera_name, video_name+".mp4" )
            
            with open(output_file, 'w', encoding='utf-8') as f:
                json.dump(self.video_queue, f, ensure_ascii=False, indent=4)
            
            self._async_execute(send_info=sendinfo)
            return jsonify({
                "status": "success",
                "message": f"摄像头任务已启动: {camera_name}",
                "resumed": (camera_name == self.run_moive_task)
            })
        except Exception as e:
            return self._error_response(str(e))

    def start_cpp_batch(self, action=None):
        output_file = "/data/video_queue_info4.json"
        try:
            data = request.get_json()
            if not data or 'camera_paths' not in data:
                return self._error_response("缺少camera_paths参数", 400)
            camera_paths = data['camera_paths']
            if not isinstance(camera_paths, list):
                return self._error_response("camera_paths必须是数组", 400)
            results = []
            for path in camera_paths:
                try:
                    modify_queue_info(self.video_queue, self.root_dir + "/" + path, queue_paused=False, custom_field=123)
                    results.append({
                        "camera_path": path,
                        "status": "success"
                    })
                except Exception as e:
                    results.append({
                        "camera_path": path,
                        "status": "error",
                        "message": str(e)
                    })
            with open(output_file, 'w', encoding='utf-8') as f:
                json.dump(self.video_queue, f, ensure_ascii=False, indent=4)
            self.is_paused = True
            self._async_execute()
            return jsonify({
                "status": "completed",
                "results": results
            })
        except Exception as e:
            return self._error_response(str(e))

    def run(self, debug=False):
        self.app.run(host=self.host, port=self.port, debug=debug)

    # async def push_single_image(self, websocket):
    #     """使用二进制协议发送文件名+图片数据"""
    #     try:
    #         while not self.ws_stop_flag.is_set():
    #             res = get_latest_image("./results/video")
    #             current_img = res
                
    #             if current_img and "stop.jpg" in current_img:
    #                 print("检测到终止条件，准备停止服务")
    #                 await self.safe_stop_ws()
    #                 break
                
    #             if current_img and os.path.exists(current_img):
    #                 with open(current_img, "rb") as f:
    #                     image_data = f.read()
                        
    #                     # 先发送文件名长度和文件名(UTF-8编码)
    #                     filename = os.path.basename(res).encode('utf-8')
    #                     await websocket.send(len(filename).to_bytes(4, 'big'))
    #                     await websocket.send(filename)
                        
    #                     # 再发送图片数据
    #                     await websocket.send(image_data)
    #                     print(f"Sent: {os.path.basename(current_img)}")
                
    #             await asyncio.sleep(self.SEND_INTERVAL)
    #     except websockets.exceptions.ConnectionClosed:
    #         print("客户端断开连接")
    #     except Exception as e:
    #         print(f"推送异常: {str(e)}")

    # async def safe_stop_ws(self):
    #     """安全停止 WebSocket 服务"""
    #     # 设置停止标志
    #     self.ws_stop_flag.set()
        
    #     # 关闭所有活跃连接
    #     if self.ws_server:
    #         self.ws_server.close()
    #         await self.ws_server.wait_closed()
        
    #     # 取消服务器任务
    #     if self.ws_server_task:
    #         self.ws_server_task.cancel()
    #         try:
    #             await self.ws_server_task
    #         except asyncio.CancelledError:
    #             pass
        
    #     print("WebSocket 服务已安全终止")

    # async def ws_server_main(self):
    #     """WebSocket 服务主任务"""
    #     self.ws_stop_flag = asyncio.Event()
        
    #     async with websockets.serve(self.push_single_image, "0.0.0.0", 8765) as server:
    #         self.ws_server = server
    #         print("WebSocket 服务已启动")
    #         await self.ws_stop_flag.wait()  # 等待停止信号
    #         print("检测到停止信号，关闭服务")

    # def start_ws_server(self):
    #     """启动 WebSocket 服务线程并保存事件循环"""
    #     def run_server():
    #         loop = asyncio.new_event_loop()
    #         asyncio.set_event_loop(loop)
    #         self.ws_server_loop = loop  # 保存事件循环引用
    #         self.ws_server_task = loop.create_task(self.ws_server_main())
    #         loop.run_until_complete(self.ws_server_task)

    #     self.ws_thread = threading.Thread(target=run_server, daemon=True)
    #     self.ws_thread.start()
    #     print("WebSocket 服务线程已启动")  

    # async def safe_stop_ws(self):
    #     """异步安全停止服务器"""
    #     self.ws_stop_flag.set()
    #     if self.ws_server:
    #         self.ws_server.close()
    #         await self.ws_server.wait_closed()
    #     if self.ws_server_task:
    #         self.ws_server_task.cancel()
    #         try:
    #             await self.ws_server_task
    #         except asyncio.CancelledError:
    #             pass

    # def stop_ws_server(self):
    #     """跨线程停止WebSocket服务器"""
    #     if self.ws_server_loop and self.ws_server_loop.is_running():
    #         # 在子线程事件循环中设置停止标记
    #         async def _safe_stop():
    #             self.ws_stop_flag.set()
    #             self.ws_server.close()
    #             await self.ws_server.wait_closed()
            
    #         # 提交停止任务到子线程循环
    #         future = asyncio.run_coroutine_threadsafe(_safe_stop(), self.ws_server_loop)
    #         try:
    #             future.result(2)  # 等待2秒完成停止
    #         except TimeoutError:
    #             print("停止服务超时")
            
    #         # 停止事件循环
    #         self.ws_server_loop.call_soon_threadsafe(self.ws_server_loop.stop)
    #         self.ws_thread.join(timeout=2)
    #         self.ws_server_loop = None
    #         print("WebSocket服务器已停止")
    
    # def set_stop_condition(self, value):
    #     """设置停止条件值（可扩展为复杂条件判断）"""
    #     self.stop_condition = value
    #     print(f"设置停止条件: {value}")

    # async def handle_connection(self, websocket, path):
    #     """处理客户端连接"""
    #     client_ip = websocket.remote_address[0]
    #     print(f"客户端连接: {client_ip}")
    #     try:
    #         await self.push_single_image(websocket)
    #     except websockets.exceptions.ConnectionClosed:
    #         print(f"客户端断开: {client_ip}")
    #     finally:
    #         await websocket.close()


if __name__ == '__main__':
    app = VideoProcessingApp()
    app.run(debug=True) 